package main

import (
	"log"
	"syscall"
	"unsafe"

	"gitee.com/general252/dllimports"
)

var (
	cStr = func(str string) uintptr {
		data, err := syscall.UTF16PtrFromString(str)
		if err != nil {
			return 0
		}
		return uintptr(unsafe.Pointer(data))
	}
	goStr = func(str []uint16) string {
		return syscall.UTF16ToString(str)
	}

	stringToUTF8Ptr = func(s string) uintptr {
		temp := []byte(s)
		utf8StrArr := make([]uint8, len(temp)+1) // +1是因为0结尾
		copy(utf8StrArr, temp)

		return uintptr(unsafe.Pointer(&utf8StrArr[0]))
	}
)

var (
	_user32         = dllimports.NewLazyDLL("User32.dll")
	_MessageBoxW    = _user32.NewProc("MessageBoxW")
	_MessageBoxA    = _user32.NewProc("MessageBoxA")
	_FindWindowW    = _user32.NewProc("FindWindowW")
	_GetWindowRect  = _user32.NewProc("GetWindowRect")
	_GetWindowTextW = _user32.NewProc("GetWindowTextW")
)

type User32 struct {
}

func (*User32) MessageBoxW(txt, caption string, t uint32) {
	r1, r2, err := _MessageBoxW.Call(0, cStr(txt), cStr(caption), uintptr(t))
	log.Println(r1, r2, err)
}

func (*User32) MessageBoxA(txt, caption string, t uint32) {
	r1, r2, err := _MessageBoxA.Call(0, stringToUTF8Ptr(txt), stringToUTF8Ptr(caption), uintptr(t))
	log.Println(r1, r2, err)
}

func (*User32) FindWindowW(caption string) (uintptr, error) {
	r1, _, err := _FindWindowW.Call(0, cStr(caption))
	if r1 == 0 {
		return 0, err
	}

	return r1, nil
}

func (*User32) GetWindowTextW(wnd uintptr) (string, error) {
	buff := make([]uint16, 255)
	r1, _, err := _GetWindowTextW.Call(wnd, uintptr(unsafe.Pointer(&buff[0])), uintptr(len(buff)))
	if r1 == 0 {
		return "", err
	}
	return goStr(buff), nil
}

type TRect struct {
	Left   int32
	Top    int32
	Right  int32
	Bottom int32
}

func (*User32) GetWindowRect(wnd uintptr) (*TRect, error) {
	var rect TRect
	r1, _, err := _GetWindowRect.Call(wnd, uintptr(unsafe.Pointer(&rect)))
	if r1 == 0 {
		return nil, err
	}
	return &rect, nil
}

func main() {
	log.SetFlags(log.LstdFlags | log.Lshortfile)

	var (
		user32 User32
		wnd    uintptr
		err    error
	)

	user32.MessageBoxW("1", "2", 2)
	user32.MessageBoxA("3", "4", 2)

	if wnd, err = user32.FindWindowW("任务管理器"); err != nil {
		log.Println(err)
	}

	if caption, err := user32.GetWindowTextW(wnd); err != nil {
		log.Println(err)
	} else {
		log.Println(caption)
	}

	if rect, err := user32.GetWindowRect(wnd); err != nil {
		log.Println(err)
	} else {
		log.Println(rect)
	}

	if rect, err := user32.GetWindowRect(0); err != nil {
		log.Println(err)
	} else {
		log.Println(rect)
	}
}
